package com.yanqu.road.server.gameplayer.module.player;

import com.yanqu.road.entity.curio.enums.eCurioConditionType;
import com.yanqu.road.entity.log.LogChildAdultReward;
import com.yanqu.road.entity.log.LogChildBirth;
import com.yanqu.road.entity.marriage.MarriageInfo;
import com.yanqu.road.entity.messageSubscribe.entity.MessageUserNoticeData;
import com.yanqu.road.entity.player.UserInfo;
import com.yanqu.road.entity.player.UserPowerChild;
import com.yanqu.road.entity.retrievereward.config.RecoveryRewardParameterConfig;
import com.yanqu.road.entity.task.args.union.UnionActivityTaskArgs;
import com.yanqu.road.logic.bussiness.player.UserChildBussiness;
import com.yanqu.road.logic.bussiness.player.UserPowerChildBussiness;
import com.yanqu.road.logic.pb.ChildPb;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.entity.child.ChildTrainResult;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.decoration.MammonEffectResult;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.player.UserBeauty;
import com.yanqu.road.entity.config.beauty.BeautyIdentityInfo;
import com.yanqu.road.entity.config.children.ChildTalentInfo;
import com.yanqu.road.entity.player.UserChildSite;
import com.yanqu.road.entity.task.args.BeautyArgs;
import com.yanqu.road.pb.assistant.AssistantProto;
import com.yanqu.road.pb.child.ChildProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.curio.CurioModule;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.retrieveReward.RecoveryRewardModule;
import com.yanqu.road.server.gameplayer.module.xiaomian.XiaoMianModule;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.DataAnalyticsMgr;
import com.yanqu.road.server.manger.RecoveryReward.RecoveryRewardMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.config.*;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.marriage.MarriageMgr;
import com.yanqu.road.server.manger.messagesubscribe.MessageSubscribeMgr;
import com.yanqu.road.server.manger.rank.RankMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.UUIDHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 子嗣模块
 */
public class ChildModule extends GeneralModule {

    private static RandomHelper threadSafeRandom = new RandomHelper();

    private Map<Integer, UserChildSite> userChildSiteMap;

    private Map<Integer, Integer> lastSaveUserChildPowerMap;    //上线前最后一次保存的用户子嗣体力数据 用于找回

    /**
     * 最强子嗣
     */
    private UserPowerChild userPowerChild;

    public ChildModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        userChildSiteMap = UserChildBussiness.getUserChildSiteMap(player.getUserId());
        userPowerChild = UserPowerChildBussiness.getUserPowerChild(player.getUserId());
        lastSaveUserChildPowerMap = new ConcurrentHashMap<>();
        for (Map.Entry<Integer, UserChildSite> entry : userChildSiteMap.entrySet()) {   //记录最后一次保存的用户子嗣体力数据 用于找回
            lastSaveUserChildPowerMap.put(entry.getKey(), entry.getValue().getTrainTimes());
        }

        try {
            for (UserChildSite userChildSite : userChildSiteMap.values()) {
                if (userChildSite.getMotherBeautyId() == 0){
                    continue;
                }
                UserBeauty userBeauty = player.getModule(BeautyModule.class).getUserBeauty(userChildSite.getMotherBeautyId());
                if (userBeauty == null) {
                    UserBeauty beauty103001 = player.getModule(BeautyModule.class).getUserBeauty(103001);
                    if (beauty103001 != null) {
                        userChildSite.setMotherBeautyId(beauty103001.getBeautyId());
                    }
                }
            }
        } catch (Exception e) {
            log.error(e);
        }
        return true;
    }

    @Override
    public boolean afterLoadData() {
        initChildSystem(false);
        return true;
    }

    @Override
    public void loginSendMsg() {
        calcAndSyncChildSite();
    }

    @Override
    public boolean saveData() {
        List<UserChildSite> siteList = new ArrayList<>(userChildSiteMap.values());
        for (UserChildSite childSite : siteList) {
            if (childSite.isInsertOption()) {
                UserChildBussiness.addUserChildSite(childSite);
            } else if (childSite.isUpdateOption()) {
                UserChildBussiness.updateUserChildSite(childSite);
            }
        }
        if (userPowerChild != null) {
            if (userPowerChild.isInsertOption()) {
                UserPowerChildBussiness.addUserChildSite(userPowerChild);
            } else if (userPowerChild.isUpdateOption()) {
                UserPowerChildBussiness.updateUserChildSite(userPowerChild);
            }
        }
        return true;
    }

    public void initChildSystem(boolean isSendMsg){
        if(SystemOpenMgr.systemOpen(player, eSystemId.Child.getValue())) {
            if(null == userChildSiteMap){
                userChildSiteMap = new ConcurrentHashMap<>();
            }
            checkChildSiteUnlock(isSendMsg);
        }
    }

    void calcAndSyncChildSite(){
        calSiteTrainTimes();
        if(null != userChildSiteMap){
            syncChildSiteData(new ArrayList<>(userChildSiteMap.values()));
        }
    }

    /**
     * 同步子嗣信息
     */
    private void syncChildSiteData(List<UserChildSite> childList) {
        player.sendPacket(Protocol.U_CHILD_SITE_SYNC, ChildPb.parseChildSiteListMsg(childList));
    }

    /**
     * 同步子嗣信息
     */
    public void syncChildSiteData(UserChildSite childSite) {
        if(null != childSite){
            List<UserChildSite> userChildSiteList = new ArrayList<>();
            userChildSiteList.add(childSite);
            syncChildSiteData(userChildSiteList);
        }
    }

    /**
     * 美女生孩子
     */
    public UserChildSite beautyMakeChild(UserBeauty userBeauty,boolean mustDouble) {
        UserChildSite childSite = getRemainingMaxTrainTimesChildSite();
        if(null == childSite) {//没有空着子嗣席位，不能增加子嗣
            return null;
        }
        BeautyIdentityInfo beautyIdentity = BeautyMgr.getBeautyIdentityInfo(userBeauty.getIdentityLv());
        childSite.setChildType(makeChildType(mustDouble));
        childSite.setChildUid(UUIDHelper.randomUUID(String.valueOf(GameServer.getInstance().getServerId())));
        childSite.setChildTalent(beautyIdentity.getChildTalent());
        childSite.setMotherBeautyId(userBeauty.getBeautyId());
        childSite.setChildSex(ChildMgr.getRandomChildSex((int) BeautyMgr.getTotalChildCount(player.getModule(BeautyModule.class).getBeautyMap())));
        childSite.setChildOccupation(ChildMgr.getRandomChildOccupation(player));
        childSite.setChildName("");
        childSite.setChildName2("");
        childSite.setChildHeadIcon(ChildMgr.getChildHeadIcon(childSite.getChildSex()));
        childSite.setCurrentGrowth(0);
        //累计子嗣数量增加
        int childCount = 1;
        if(childSite.getChildType() != 0){
            childCount = 2;
        }
        userBeauty.setChildCount(userBeauty.getChildCount() + childCount);
        syncChildSiteData(childSite);
        //成就、任务
        player.notifyListener(eGamePlayerEventType.ChildTotalCount.getValue(), new BeautyArgs(player.getModule(BeautyModule.class).getBeautyMap()));

        AutoLogMgr.add(new LogChildBirth(player.getUserId(), childSite.getChildTalent(), childSite.getSiteIndex(), childSite.getChildType() != 0,
                userBeauty.getBeautyId(), userBeauty.getTotalIntimacy(), childSite.getChildUid()));
        DataAnalyticsMgr.trackChildGetPupil(player,childSite);
        return childSite;
    }

    /**
     * @param mustDouble bool 是否必定双胞胎
     * @return int
     */
    private int makeChildType(boolean mustDouble){
        if(mustDouble || GameConfig.BEAUTY_TRYST_MAKE_DOUBLE_CHILD_WEIGHT > threadSafeRandom.next(0, 1000)){
            return threadSafeRandom.next(1,5);
        }
        return 0;
    }

    /**
     * 子嗣培养
     * @param siteIndex 位置序号
     * @param childUid 子嗣ID
     * @param type
     * @param trainTimes 培养次数
     * @param currentChildUid 当前界面上的子嗣
     * @return
     */
    public ChildTrainResult childTrain(int siteIndex, String childUid, int type, int trainTimes, String currentChildUid) {
        ChildTrainResult result = new ChildTrainResult();
        UserChildSite userChildSite = getUserChildSite(siteIndex);
        if (null == userChildSite) {//子嗣席位未找到
            result.setRet(GameErrorCode.E_CHILD_SITE_NO_FOUND);
            return result;
        }

        if (userChildSite.getTrainType() == 0) {//没有培养类型
            result.setRet(GameErrorCode.E_CHILD_TRAIN_TYPE_ERROR);
            return result;
        }

        if(StringUtils.isNullOrEmpty(childUid)){
            result.setRet(GameErrorCode.E_CHILD_NO_FOUND);
            return result;
        }

        if(!Objects.equals(userChildSite.getChildUid(), childUid)){
            result.setRet(GameErrorCode.E_CHILD_SITE_HAS_CHANGE);
            return result;
        }
        // 是否已经培养完成
        ChildTalentInfo childTalent = ChildMgr.getChildTalentInfo(userChildSite.getChildTalent());
        if (userChildSite.getCurrentGrowth() >= childTalent.getTotalGrowth()) {
            result.setRet(GameErrorCode.E_CHILD_TRAIN_COMPLETE);
            return result;
        }

        calcSiteTrainTimes(userChildSite);
        if (userChildSite.getTrainTimes() < 1) {
            //同步培养次数给客户端
            syncChildSiteData(userChildSite);
            //触发现金礼包，活力丹道具不足
//            if(!player.getModule(BagModule.class).hasEnoughGoods(GameConfig.GAME_ITEM_CHILD_ADD_TRAIN_TIMES, 1)) {
//            }
            //当前界面上的子嗣没体力才触发礼包
            if (childUid.equals(currentChildUid)) {
                player.notifyListener(eGamePlayerEventType.RechargeChildTrain.getValue(), 0);
                //没有活力
                player.notifyListener(eGamePlayerEventType.RechargeChildTrainNew.getValue(), 0);
            }
            result.setRet(GameErrorCode.E_CHILD_TRAIN_TIMES_NO_ENOUGH);
            return result;
        }

        if(1 == type){//一键培养
            if(!player.getModule(CardModule.class).isOneKeyTrainChild()
                && !player.getModule(CardModule.class).isOneKeyTrainAllChild()){
                result.setRet(GameErrorCode.E_CHILD_CAN_NO_VIP_TRAIN);
                return result;
            }
            result = doTrain(userChildSite, true, trainTimes);
        }else {
            result = doTrain(userChildSite, false, trainTimes);
        }

        calcSiteTrainTimes(userChildSite);
        //同步
        syncChildSiteData(userChildSite);
        try {
            trainTimesRecoveryTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
        return result;
    }

    //计算什么时候就全满了，设置一个提醒时间
    private void trainTimesRecoveryTime(){
        if(!MessageSubscribeMgr.isSwitch()){
            return;
        }
        long nowTime = System.currentTimeMillis();
        long recoveryTime = 0;
        int maxTrainTimes = ChildMgr.getChildSiteMaxTrainTimes(player);
        int recoveryNeedTime = GameConfig.CHILDREN_RESTORE_TRAIN_TIME;
        int maxNeed = 0;
        for(UserChildSite userChildSite : userChildSiteMap.values()){
            if(userChildSite.getTrainTimes() <= maxTrainTimes){
                if(maxNeed < maxTrainTimes - userChildSite.getTrainTimes()){
                    maxNeed = maxTrainTimes - userChildSite.getTrainTimes();
                }
            }
        }
        if(maxNeed > 0){
            recoveryTime = nowTime + recoveryNeedTime * maxNeed * 1000;
        }
        MessageUserNoticeData noticeData = MessageSubscribeMgr.getUserNoticeData(player.getUserId());
        noticeData.setSonTime(recoveryTime);
    }

    /**
     * 执行培养
     * @param trainTimes  培养次数
     */
    private ChildTrainResult doTrain(UserChildSite userChildSite, boolean isOneKeyTrain, int trainTimes){
        ChildTrainResult result = new ChildTrainResult();
        ChildTalentInfo childTalent = ChildMgr.getChildTalentInfo(userChildSite.getChildTalent());

        //消耗活力的倍数
        int costMultiple = 1;
        if(userChildSite.isComprehend()){
            costMultiple = GameConfig.CHILDREN_CHANGE_ICO_FAIRY_MULTIPLE;
        }

        int needTimes = (childTalent.getTotalGrowth() - userChildSite.getCurrentGrowth() + childTalent.getTrainAddGrowth() - 1) / childTalent.getTrainAddGrowth();

        //需要消耗的活力
        int needCost = needTimes * costMultiple;

        if (needCost > userChildSite.getTrainTimes()) {
            needTimes = userChildSite.getTrainTimes() / costMultiple;
        }

        if(userChildSite.getTrainCostSilver().compareTo(BigInteger.ZERO) > 0) {
            BigInteger times = player.getUserInfo().getSilver().divide(userChildSite.getTrainCostSilver());
            if(times.compareTo(BigInteger.valueOf(needTimes)) < 0){
                needTimes = times.intValue();
            }
        }
        if(!isOneKeyTrain) {
            if(trainTimes < 1){
                trainTimes = 1;
            }
            if(trainTimes < needTimes){
                needTimes = trainTimes;
            }
        }
        long onceAddExp = ChildMgr.getTrainChildAddExp(player, childTalent, userChildSite);
        BigInteger addExp = BigInteger.ZERO;
        for(int i = 0; i < needTimes; i++){
            MammonEffectResult effectResult = player.getModule(MammonModule.class).isMammonSkillEffect(eSkillType.MammonChildTrainAddPatronsExp.getValue(), onceAddExp);
            if(effectResult.getEffectMammonSkill() > 0){
                result.setEffectMammonSkill(effectResult.getEffectMammonSkill());
                result.setEffectTimes(result.getEffectTimes() + 1);
                addExp = addExp.add(BigInteger.valueOf(effectResult.getValue()));
            }
            if(effectResult.isOverMaxEffectTimes()){
                break;
            }
        }
        //成长加成
        int growAddition = ChildMgr.getChildGrowStageAddition(userChildSite.getCurrentGrowth(), needTimes, childTalent.getTrainAddGrowth());
        //扣除培养次数（活力）
        userChildSite.setTrainTimes(userChildSite.getTrainTimes() - needTimes * costMultiple);
        //扣除银两
        BigInteger costSilverNum = userChildSite.getTrainCostSilver().multiply(BigInteger.valueOf(needTimes));
        player.getModule(CurrencyModule.class).removeCurrency(new Property(GameConfig.GAME_MONEY_SILVER, costSilverNum),
                eLogMoneyType.Child, eLogMoneyType.ChildTrain);
        //2023 12 13 hyq 小助手需要
        result.setCost(costSilverNum);
        result.setRealTimes(needTimes);
        //进度增加
        int totalGrowth = userChildSite.getCurrentGrowth() + childTalent.getTrainAddGrowth() * needTimes;
        if(totalGrowth > childTalent.getTotalGrowth()){
            totalGrowth = childTalent.getTotalGrowth();
        }
        userChildSite.setCurrentGrowth(totalGrowth);
        //增加成长赚速
        if(growAddition > 0) {
            UserBeauty userBeauty = player.getModule(BeautyModule.class).getUserBeauty(userChildSite.getMotherBeautyId());
            if(userChildSite.getChildType() == 0) {
                BigInteger growEarnSpeed = ChildMgr.getChildGrowEarnSpeed(player, userChildSite.getTrainType(), userChildSite.getChildTalent(),
                        userChildSite.getChildOccupation(), userBeauty.getTotalIntimacy(), userChildSite.getChildSex(), growAddition);
                BigInteger addEarnSpeed = ChildMgr.getGrowAddEarnSpeed(userChildSite, growEarnSpeed, 0);
                userChildSite.setGrowAddEarnSpeed(growEarnSpeed);
                //增加子嗣赚速
                notifyAddChildEarnSpeed(userChildSite.getChildUid(), addEarnSpeed);
            }else {
                int position = 1;
                BigInteger growEarnSpeed = ChildMgr.getChildGrowEarnSpeed(player, userChildSite.getTrainType(), userChildSite.getChildTalent(),
                        userChildSite.getChildOccupation(), userBeauty.getTotalIntimacy(), ChildMgr.getChildSexByPosition(userChildSite,position), growAddition);
                BigInteger addEarnSpeed = ChildMgr.getGrowAddEarnSpeed(userChildSite, growEarnSpeed, position);
                userChildSite.setGrowAddEarnSpeed(growEarnSpeed);

                position = 2;
                BigInteger growEarnSpeed2 = ChildMgr.getChildGrowEarnSpeed(player, userChildSite.getTrainType(), userChildSite.getChildTalent(),
                        userChildSite.getChildOccupation(), userBeauty.getTotalIntimacy(), ChildMgr.getChildSexByPosition(userChildSite, position), growAddition);
                BigInteger addEarnSpeed2 = ChildMgr.getGrowAddEarnSpeed(userChildSite, growEarnSpeed2, position);
                userChildSite.setGrowAddEarnSpeed2(growEarnSpeed2);
                //增加子嗣赚速
                notifyAddChildEarnSpeed(userChildSite.getChildUid(), addEarnSpeed.add(addEarnSpeed2));
            }
        }
        //增加累计培养次数
        long totalTrainTimes = player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.ChildTotalTrainTimes);
        totalTrainTimes += needTimes;
        player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.ChildTotalTrainTimes, totalTrainTimes);
        //产出
        addExp = addExp.add(BigInteger.valueOf(onceAddExp).multiply(BigInteger.valueOf(needTimes - result.getEffectTimes())));
        Property reward = new Property(GameConfig.GAME_MONEY_PATRONS_EXP, addExp); //阅历
        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.Child, eLogMoneyType.ChildTrain);
        //成就、任务
        player.notifyListener(eGamePlayerEventType.ChildTrainTimes.getValue(), needTimes);
        player.notifyListener(eGamePlayerEventType.UnionChildTrainTimes.getValue(), new UnionActivityTaskArgs(UnionActivityTaskArgs.TYPE_ADD_VALUE, needTimes, player.getUserInfo().getUnionUid()));
        player.notifyListener(eGamePlayerEventType.ChildTotalTrainTimes.getValue(), totalTrainTimes);
        //小面任务
        player.getModule(XiaoMianModule.class).addChildTrainTimes(needTimes);

//        //培养后，当前活力丹不足。6.4.0优化，要重新点击才触发
//        if(totalGrowth != childTalent.getTotalGrowth()){
//            if(userChildSite.getTrainTimes() < 1){
//                player.notifyListener(eGamePlayerEventType.RechargeChildTrainNew.getValue(), 0);
//            }
//        }
        return result;
    }

    /**
     * 增加子嗣赚速
     */
    public void notifyAddChildEarnSpeed(String childUid, BigInteger addEarnSpeed){
        //赚速加到玩家身上
        UserInfo userInfo = player.getUserInfo();
        BigInteger oldEarnSpeed = userInfo.getChildEarnSpeed();
        userInfo.setChildEarnSpeed(userInfo.getChildEarnSpeed().add(addEarnSpeed));
        LogMgr.addLogChildAddEarnSpeed(player.getUserId(), childUid, 0, oldEarnSpeed, addEarnSpeed, userInfo.getChildEarnSpeed());
        //冲榜
        player.notifyListener(eGamePlayerEventType.ChildEarnSpeedRiseRank.getValue(), addEarnSpeed);
        //重新计算赚速
        player.getModule(EarnSpeedModule.class).scheduleAddSilver();
    }

    /**
     * 检测席位解锁
     */
    void checkChildSiteUnlock(boolean isSendMsg) {
        int siteCount = getChildSiteCount();
        if (ChildMgr.isSiteMax(siteCount)) {//是否达到上限
            return;
        }
        int unlockCount = ConfigMgr.getChildSiteUnlockCount(player.getTitleId());
        if(unlockCount > siteCount){
            List<UserChildSite> syncList = new ArrayList<>();
            for(int siteIndex = siteCount + 1; siteIndex <= unlockCount; siteIndex++){
                if(!userChildSiteMap.containsKey(siteIndex)){
                    UserChildSite childSite = initUserChildSite(siteIndex);
                    userChildSiteMap.put(childSite.getSiteIndex(), childSite);
                    syncList.add(childSite);
                }
            }
            if(syncList.size() > 0 && isSendMsg){
                syncChildSiteData(syncList);
            }
        }
    }

    /**
     * 使用道具恢复培养次数
     */
    public int childSiteTrainTimesRecover(int siteIndex, int goodsId, int useCount) {
        if(useCount < 1){
            return GameErrorCode.E_BAG_USE_GOODS_COUNT_LESS_ONE;
        }

        UserChildSite userChildSite = getUserChildSite(siteIndex);
        if (null == userChildSite) {//未找到席位
            return GameErrorCode.E_CHILD_SITE_NO_FOUND;
        }

        //检测道具合法性
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(goodsId);
        if (!GoodsMgr.isChildSiteTrainTimesRecover(goodsInfo)) {
            return GameErrorCode.E_BAG_GOODS_NO_CHILD_SITE_TRAIN_TIMES_RECOVER;
        }

        Property property = new Property(goodsId, BigInteger.valueOf(useCount));
        //消耗
        if (!player.getModule(CurrencyModule.class).removeCurrency(property, eLogMoneyType.Child, eLogMoneyType.ChildTrainTimesRecover)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        int addTrainTimes = goodsInfo.getParamList().get(0).intValue();
        //增加培养次数
        userChildSite.setTrainTimes(userChildSite.getTrainTimes() + (addTrainTimes * useCount));
        syncChildSiteData(userChildSite);
        try {
            trainTimesRecoveryTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
        return 0;
    }

    public void clearChildSite(UserChildSite userChildSite){
        if(null != userChildSite) {
            userChildSite.setChildUid("");
            userChildSite.setChildTalent(0);
            userChildSite.setMotherBeautyId(0);
            userChildSite.setChildSex(0);
            userChildSite.setChildOccupation(0);
            userChildSite.setChildName("");
            userChildSite.setChildHeadIcon(0);
            userChildSite.setCurrentGrowth(0);
            userChildSite.setTrainType(0);
            userChildSite.setTrainCostSilver(BigInteger.ZERO);
            userChildSite.setGrowAddEarnSpeed(BigInteger.ZERO);
            userChildSite.setGrowAddEarnSpeed2(BigInteger.ZERO);
            userChildSite.setComprehend(false);
        }
    }

    /**
     * 获取剩余空着子嗣席位数量
     */
    public int getRemainingChildSiteCount() {
        int count = 0;
        for(UserChildSite childSite : userChildSiteMap.values()){
            if(StringUtils.isNullOrEmpty(childSite.getChildUid())){
                count++;
            }
        }
        return count;
    }

    /**
     * 获取最多培养次数子嗣席位
     */
    private UserChildSite getRemainingMaxTrainTimesChildSite() {
        UserChildSite resultSite = null;
        int trainTimes = Integer.MIN_VALUE;
        for(UserChildSite childSite : userChildSiteMap.values()){
            if(StringUtils.isNullOrEmpty(childSite.getChildUid())){
                if(childSite.getTrainTimes() > trainTimes){
                    trainTimes = childSite.getTrainTimes();
                    resultSite = childSite;
                }
            }
        }
        return resultSite;
    }

    public int getChildSiteCount() {
        return userChildSiteMap.size();
    }

    private void calSiteTrainTimes(){
        for(UserChildSite userChildSite : userChildSiteMap.values()){
            calcSiteTrainTimes(userChildSite);
        }
    }

    /**
     * 计算培训次数
     */
    private void calcSiteTrainTimes(UserChildSite childSite) {
        long nowTime = System.currentTimeMillis() / 1000;
        long lastRestoreTime = childSite.getLastRestoreTime();
        int maxTrainTimes = ChildMgr.getChildSiteMaxTrainTimes(player);

        int trainRestoreTime = GameConfig.CHILDREN_RESTORE_TRAIN_TIME;
        //藏品加成
        int addition = (int)CurioMgr.getSkillAdditionBySkillType(eSkillType.ChildEnergyRecoverySkill.getValue(), player, 0);
        trainRestoreTime -= addition;

        if(childSite.getTrainTimes() < maxTrainTimes) {
            //恢复次数
            int restoreTimes = (int) ((nowTime - lastRestoreTime) / trainRestoreTime);
            if (restoreTimes < 0) {
                restoreTimes = 0;
            }

            int trainTimes = childSite.getTrainTimes();
            // 当前值 + 恢复指 如果超过最大值
            if (restoreTimes + trainTimes >= maxTrainTimes) {
                trainTimes = maxTrainTimes;
                childSite.setLastRestoreTime(nowTime);
            } else {
                trainTimes = trainTimes + restoreTimes;
                childSite.setLastRestoreTime(lastRestoreTime + trainRestoreTime * restoreTimes);
            }
            childSite.setTrainTimes(trainTimes);
        }else {
            childSite.setLastRestoreTime(nowTime);
        }
    }

    public UserChildSite getUserChildSite(int siteIndex) {
        return userChildSiteMap.get(siteIndex);
    }

    /**
     * 获取未成年子嗣数量
     */
    public int getUnAdultChildCount(){
        int count = 0;
        for(UserChildSite userChildSite : userChildSiteMap.values()){
            if(!StringUtils.isNullOrEmpty(userChildSite.getChildUid())){
                int childCount = 1;
                if(userChildSite.getChildType() != 0){
                    childCount = 2;
                }
                count += childCount;
            }
        }
        return count;
    }

    /**
     * 获取成年子嗣数量
     */
    public long getAdultChildCount(){
        long count = BeautyMgr.getTotalChildCount(player.getModule(BeautyModule.class).getBeautyMap());
        count = count - getUnAdultChildCount();
        if(count < 0){
            count = 0;
        }
        return count;
    }

    private UserChildSite initUserChildSite(int siteIndex) {
        UserChildSite childSite = new UserChildSite();
        childSite.setUserId(player.getUserId());
        childSite.setSiteIndex(siteIndex);
        childSite.setTrainTimes(ChildMgr.getChildSiteMaxTrainTimes(player));
        childSite.setLastRestoreTime(System.currentTimeMillis() / 1000);
        childSite.setChildUid("");
        childSite.setChildTalent(0);
        childSite.setMotherBeautyId(0);
        childSite.setChildSex(0);
        childSite.setChildOccupation(0);
        childSite.setChildName("");
        childSite.setChildName2("");
        childSite.setChildHeadIcon(0);
        childSite.setCurrentGrowth(0);
        childSite.setChildType(0);
        childSite.setInsertOption();
        return childSite;
    }


    /**
     * 子嗣成年后判断是否是最强子嗣，并且更新到排行榜
     */
    public void adultChild(MarriageInfo marriageInfo){
        if (userPowerChild != null && userPowerChild.getChildEarnSpeed().compareTo(marriageInfo.getChildEarnSpeed()) > 0) {
            return;
        }
        // 更新最强子嗣信息
        setUserPowerChild(marriageInfo);
        // 刷新排行
        RankMgr.changeChildRank(player.getUserId(), userPowerChild);
    }

    /**
     * 子嗣成年后判断是否是最强子嗣，并且更新到排行榜
     */
    public BigInteger getPowerChildEarnSpeed(){
        if (userPowerChild == null) {
            return BigInteger.ZERO;
        }
        return userPowerChild.getChildEarnSpeed();
    }

    private void setUserPowerChild(MarriageInfo marriageInfo){
        if (userPowerChild == null) {
            userPowerChild = new UserPowerChild();
            userPowerChild.setUserId(player.getUserId());
            userPowerChild.setInsertOption();
        }
        userPowerChild.setChildUid(marriageInfo.getChildUid());
        userPowerChild.setChildTalent(marriageInfo.getChildTalent());
        userPowerChild.setChildSex(marriageInfo.getChildSex());
        userPowerChild.setChildOccupation(marriageInfo.getChildOccupation());
        userPowerChild.setChildName(marriageInfo.getChildName());
        userPowerChild.setChildHeadIcon(marriageInfo.getChildHeadIcon());
        userPowerChild.setChildAdultTime(marriageInfo.getChildAdultTime());
        userPowerChild.setMotherBeautyId(marriageInfo.getMotherBeautyId());
        userPowerChild.setChildOccupationId(marriageInfo.getChildOccupationId());
        userPowerChild.setChildEarnSpeed(marriageInfo.getChildEarnSpeed());
        UserBeauty userBeauty = player.getModule(BeautyModule.class).getUserBeauty(marriageInfo.getMotherBeautyId());
        userPowerChild.setMotherThenIntimacy(userBeauty.getTotalIntimacy());
        userPowerChild.setIsTwins(marriageInfo.isTwins());
        userPowerChild.setUpdateOption();
    }

    public int recoveryRewardFindBackPower(int days ,RecoveryRewardParameterConfig recoveryRewardParameterConfig) {
        //先拿配置
        int recoveryNeedTime = GameConfig.CHILDREN_RESTORE_TRAIN_TIME;
        //上限
        int maxTrainTimes = ChildMgr.getChildSiteMaxTrainTimes(player);
        //需要恢复的体力


        if (lastSaveUserChildPowerMap == null || lastSaveUserChildPowerMap.isEmpty()){
            log.error("userId {}子嗣系统已解锁但未取得上次登录时体力数据,未找回体力,原应找回{}天",getUserId(),days);
            return 0;
        }
        int recoveryPowerSum = 0;

        for (Map.Entry<Integer,Integer>entry:lastSaveUserChildPowerMap.entrySet()){
            UserChildSite childSite = userChildSiteMap.get(entry.getKey());
            if (childSite != null){
                int shouldRecoveryTimes =  player.getModule(RecoveryRewardModule.class).calculateShouldRetrieveTimesByOneDayRecovery(maxTrainTimes, recoveryNeedTime, recoveryRewardParameterConfig.getDiscountParameter(),entry.getValue(),days) ;
                if (shouldRecoveryTimes > 0){
                    childSite.setTrainTimes(childSite.getTrainTimes() + shouldRecoveryTimes);
                    recoveryPowerSum += shouldRecoveryTimes;
                }

            }
        }
        syncChildSiteData(new ArrayList<>(userChildSiteMap.values()));
        return recoveryPowerSum;
    }

    /**
     * 子嗣成年
     * @param userChildSite
     * @param position
     * @return
     */
    public ChildProto.ChildAdultTempMsg.Builder adultChild(UserChildSite userChildSite, int position){

        long adultCount = player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.ChildTotalAdultCount);
        boolean isLonely = ChildMgr.isLonely(adultCount);

        int occupationId = ChildMgr.getRandomOccupationId(userChildSite.getChildOccupation(), ChildMgr.getChildSexByPosition(userChildSite, position), isLonely);

        int childOccupationAddition = ChildMgr.getChildOccupationAddition(occupationId);
        int curioAddition = (int) CurioMgr.getSkillAdditionBySkillType(eSkillType.CurioChildAdultAddSkill.getValue(), player, userChildSite.getChildOccupation());
        UserBeauty mother = player.getModule(BeautyModule.class).getUserBeauty(userChildSite.getMotherBeautyId());

        MarriageInfo temp = new MarriageInfo();
        //获得子嗣赚速
        BigInteger childEarnSpeed = ChildMgr.getChildAdultEarnSpeed(player, userChildSite.getTrainType(), userChildSite.getChildTalent(), userChildSite.getChildOccupation(),
                childOccupationAddition + curioAddition, mother.getTotalIntimacy(), isLonely, ChildMgr.getChildSexByPosition(userChildSite,position), temp);
        BigInteger addEarnSpeed = ChildMgr.getGrowAddEarnSpeed(userChildSite, childEarnSpeed, position);
        player.getModule(ChildModule.class).notifyAddChildEarnSpeed(userChildSite.getChildUid(), addEarnSpeed);
        //获得道具奖励
        Property reward = ChildMgr.getChildAdultReward(userChildSite.getChildTalent(), userChildSite.getChildOccupation(), isLonely);
        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.Child, eLogMoneyType.ChildAdult);

        //成年，加入联姻管理
        MarriageInfo marriageInfo = MarriageMgr.addToMarriage(player, userChildSite, reward, childEarnSpeed, isLonely, childOccupationAddition, occupationId,position);
        marriageInfo.setCurioAddition(temp.getCurioAddition());

        //记录最强子嗣
        player.getModule(ChildModule.class).adultChild(marriageInfo);

        adultCount++;
        player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.ChildTotalAdultCount, adultCount);

        ChildProto.ChildAdultTempMsg.Builder childTempMsg = ChildProto.ChildAdultTempMsg.newBuilder();
        childTempMsg.setReward(PropertyHelper.parsePropertyToString(reward));
        childTempMsg.setChildEarnSpeed(childEarnSpeed.toString());
        childTempMsg.setIsLonely(isLonely);
        childTempMsg.setChildOccupationId(occupationId);
        childTempMsg.setOccupationAddition(childOccupationAddition);
        childTempMsg.setCurioAddition(curioAddition);
        if(position == 0){
            childTempMsg.setIsTwins(false);
        }else{
            childTempMsg.setIsTwins(true);
        }

        DataAnalyticsMgr.trackPupilAdult(player, userChildSite, childEarnSpeed, isLonely);
        player.getModule(CurioModule.class).addUserCurioCountData(eCurioConditionType.ChildAdultNumByOccupation.getType(), userChildSite.getChildOccupation(), 1);

        // 加个日志
        AutoLogMgr.add(new LogChildAdultReward(player.getUserId(), position == 2 ? (userChildSite.getChildUid() + "-2") : userChildSite.getChildUid(), PropertyHelper.parsePropertyToString(reward)));
        return childTempMsg;
    }

    /**
     * 子嗣自动培养
     */
    public void childAutoTrain(AssistantProto.AssistantChildTrainRespMsg.Builder builder, boolean openComprehend) {
        int totalTime = 0;
        BigInteger cost = BigInteger.ZERO;
        int maxChildrenMarriageSite = GameConfig.CHILDREN_MARRIAGE_SITE;
        maxChildrenMarriageSite += CurioMgr.getSkillAdditionBySkillType(eSkillType.ChildUnMarriageLimitSkill.getValue(), player, 0);

        for(UserChildSite site:userChildSiteMap.values()){
            String childUid = site.getChildUid();
            //没有娃娃的坑 不管
            if (childUid.isEmpty()){
                continue;
            }

            if (site.getTrainType() == 0) {//没有培养类型 就是还没赐名
                // 选择最好的培养类型
                int titleId = player.getTitleId();
                int maxTrainType = ChildMgr.getMaxTrainType(titleId);
                //如果类型有问题 不能赐名 不然会炸
                if (maxTrainType <= 0){
                    log.error("userId = {},titleId为{}的玩家找不到最大培养类型,无法一键赐名小孩",player.getUserId(),titleId);
                    continue;
                }
                BigInteger trainCostSilver = ChildMgr.getTrainCostSilver(player.getTitleId(), maxTrainType, getChildSiteCount());
                if (trainCostSilver.compareTo(BigInteger.ZERO)<=0){
                    log.error("userId = {},titleId为{}的玩家找不到最大培养类型,无法一键赐名小孩",player.getUserId(),titleId);
                    continue;
                }

                String name = "";
                String name2 = "";

                int sex1 = 0;
                int sex2 = 0;
                if(site.getChildType() > 0){
                    sex1 = ChildMgr.getChildSexByPosition(site, 1);
                    sex2 = ChildMgr.getChildSexByPosition(site, 2);
                }else {
                    sex1 = site.getChildSex();
                }
                String language = player.getLanguage();
                name = ChildMgr.getRandomChildName(sex1, language);
                if(sex2 > 0){
                    name2 = ChildMgr.getRandomChildName(sex2, language);
                }
                //先赐名
                site.setChildName(name);
                site.setChildName2(name2);
                //看看有没有开启仙童 配不配开启
                ChildTalentInfo childTalentInfo = ChildMgr.getChildTalentInfo(site.getChildTalent());
                if (openComprehend && childTalentInfo.getId() == 10012){
                    site.setComprehend(true);
                }else {
                    site.setComprehend(false);
                }

                site.setTrainType(maxTrainType);
                site.setTrainCostSilver(trainCostSilver);
            }

            calcSiteTrainTimes(site);
            //如果可以的次数>0
            if (site.getTrainTimes() > 0) {
                int trainTimes = site.getTrainTimes();
                ChildTrainResult result = doTrain(site, true, trainTimes);
                calcSiteTrainTimes(site);
                totalTime += result.getRealTimes();
                cost = cost.add(result.getCost());
            }
            // 是否已经培养完成
            ChildTalentInfo childTalent = ChildMgr.getChildTalentInfo(site.getChildTalent());
            if (site.getCurrentGrowth() >= childTalent.getTotalGrowth()) {
                //是否有足够席位
                int unMarryCount = MarriageMgr.getUnMarryChildCount(player.getUserId());
                //如果可以成年
                if (unMarryCount < maxChildrenMarriageSite) {
                    UserChildSite cloneSite = site.clone();     //克隆一份出来用

                    //先清除席位信息
                    clearChildSite(site);

                    //生双胞胎
                    if(cloneSite.getChildType() != 0){
                        AssistantProto.AssistantChildAdultDetail.Builder adultBuilder1 = AssistantProto.AssistantChildAdultDetail.newBuilder();
                        ChildProto.ChildAdultTempMsg.Builder adultChild = adultChild(cloneSite, 1);
                        adultBuilder1.setChildUid(childUid);
                        adultBuilder1.setAdultMsg(adultChild);
                        builder.addChildRespMsg(adultBuilder1);


                        AssistantProto.AssistantChildAdultDetail.Builder adultBuilder2 = AssistantProto.AssistantChildAdultDetail.newBuilder();
                        ChildProto.ChildAdultTempMsg.Builder adultChild1 = adultChild(cloneSite, 2);
                        adultBuilder2.setChildUid(childUid+"-2");
                        adultBuilder2.setAdultMsg(adultChild1);
                        builder.addChildRespMsg(adultBuilder2);

                    }else{
                        AssistantProto.AssistantChildAdultDetail.Builder adultBuilder1 = AssistantProto.AssistantChildAdultDetail.newBuilder();
                        ChildProto.ChildAdultTempMsg.Builder adultChild = adultChild(cloneSite, 0);
                        adultBuilder1.setChildUid(childUid);
                        adultBuilder1.setAdultMsg(adultChild);
                        builder.addChildRespMsg(adultBuilder1);

                    }


                    //成就、任务
                    player.notifyListener(eGamePlayerEventType.ChildTotalAdultCount.getValue(), player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.ChildTotalAdultCount));
                }
                syncChildSiteData(site);
                continue;// 跳过
            }

            //同步
            syncChildSiteData(site);
        }
        builder.setTrainTime(totalTime);
        builder.setCostSliver(cost.toString());

        try {
            trainTimesRecoveryTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
    }
}
